package com.shiliu.api.common.utils;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @description: JWT工具类
 * @author: shiliu
 * @created: 2019/12/23 15:06
 * @version: v1.0.0
 */
@Slf4j
public class JwtUtil {

    /**
     * 本地加密密文
     */
    private static final String JWT_SECRET = "123";

    /**
     * 默认的过期时间为 << 30 >> 分钟(毫秒)
     */
    private static final long DEFAULT_EXPIRE = 30 * 60 * 1000;

    /**
     * 创建jwt
     *
     * @param subject   主题
     * @param ttlMillis 过期时间(如果不设置,默认的是30分钟)
     * @return
     */
    public static String generateToken(String userId,String subject, long ttlMillis) {
        // HMAC using SHA-256:
        SignatureAlgorithm signature = SignatureAlgorithm.HS256;
        // 获取当前时间:
        long nowMillis = System.currentTimeMillis();
        //
        Map<String,Object> claims = new HashMap<>();
        claims.put("userId",userId);
        claims.put("user",subject);
        JwtBuilder jwtBuilder = Jwts.builder()
                .setId(UUID())
                // 代表这个JWT的主体，即它的所有人，这个是一个json格式的字符串，可以存放什么userid，roldid之类的，作为用户的唯一标志
                .setSubject(subject)
                .setHeaderParam("typ", "jwt")
                .setClaims(claims)
                .setIssuedAt(new Date(nowMillis)) // jwt的签发时间
                .signWith(signature, generalKey());// 设置签名使用的签名算法和签名使用的秘钥
        // 设置过期时间:
        Date ttlTime;
        if (ttlMillis > 0) {
            ttlTime = new Date(nowMillis + ttlMillis);
        } else {
            // 默认过期时间30分钟
            ttlTime = new Date(nowMillis + DEFAULT_EXPIRE);
        }
        jwtBuilder.setExpiration(ttlTime); // 设置JWT过期时间
        return  jwtBuilder.compact();
    }

    /**
     * 解析token
     *
     * @param jwt
     * @return
     */
    public static Claims parseToken(String jwt){
        Claims body = Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(jwt)
                .getBody();
        return body;
    }

    /**
     * 由字符串生成加密key(可以是非对称加密的私钥)
     *
     * @return
     */
    public static SecretKey generalKey() {
        //加密的密文
        String stringKey = Base64.encodeBase64String(JWT_SECRET.getBytes());
        //本地的密码解码
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        // 根据给定的字节数组使用AES加密算法构造一个密钥，使用 encodedKey中的始于且包含 0 到前 length 个字节
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    public static String UUID(){
        return UUID.randomUUID().toString().replace("-","");
    }

}
